#ifndef _TABLE_ATTRIBUTE_DESC_H_
#define _TABLE_ATTRIBUTE_DESC_H_

#include <buildspec.h>
#include <GSTenums.h>
#include <exceptions/GSTRuntimeException.h>
#include <Utils/Converter.h>
#include <string>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <Geometry/boost_serialize_includes.hpp>


namespace GST {

	//exceptions:
	//see below class!

namespace Geometry {
	class SimplexProperty;
}

namespace ClientUtils {

	//prototype:
	class TableAttributeVal;
	class FeatureClassDesc;
	typedef boost::shared_ptr<TableAttributeVal> TableAttributeValPtr;

	/**
	 * A Description of a table attribute (without its value).
	 */
class GST_API_EXPORT TableAttributeDesc
{	
	friend class boost::serialization::access; 

public:

	enum DType {
		TypeSerial,
		TypeBool,
		TypeInt,
		TypeLong,
		TypeFloat,
		TypeVecFloat, 
		TypeDouble, 
		TypeText,
		TypeBinary,
		TypeUnkown
	};

	/**
	  * DType to data model string (as used in table constraints)
	  */
	static std::string DTypeToDMString(DType dtype);
	/**
	* Data model string (used in table constraints) to DType
	*/
	static DType DMStringToDType(const std::string & type);

	//TableAttributeDesc(const std::string& name, const std::string& tablename, DType type, int dimension, bool notNull = false);
	TableAttributeDesc(const std::string& name, const std::string& tablename, DType type, int dimension, bool notNull = false, const std::string& alternativeType = "", const int& colIndex=-1, const long& id = -1);
	TableAttributeDesc();
	TableAttributeDesc(const TableAttributeDesc& other);
	TableAttributeDesc& operator = (const TableAttributeDesc& src);
	virtual ~TableAttributeDesc() { ///@todo: implement me!
	}

	///@name setters/getters
	//@{
	virtual std::string getName() const;
	virtual void setName(const std::string& name);
	virtual std::string getTableName() const;
	virtual void setTableName(const std::string& tname);
	virtual DType getType() const;
	void setType(DType dtype);
	virtual int getDimension() const;
	virtual void setAlternativeType(const std::string & typeStr);
	virtual std::string getAlternativeType() const { return this->alternativeTypeString; }
	virtual int getColIndex() const { return this->colIndex; }
	virtual int getId() const { return this->id; }
	virtual void setId(const int& id)  { this->id = id; }
	virtual void setNotNull(bool notNull);
	virtual bool isNotNull() const;
	virtual TableAttributeDesc * clone() const;
	//@}

	virtual bool operator==(const TableAttributeDesc &other) const;
	bool compareDtype(const DType & datatype, const std::string alternativeDType = "") const;
	bool compareNames(const std::string& name, const std::string& othername ) const;
protected:
	std::string tablename;
	std::string name;
	int dimension;
	DType datatype;
	std::string alternativeTypeString;
	bool notNull;
	int colIndex;
	long id;

private:
	template <typename Archive> 
	void serialize(Archive &ar, const unsigned int version) 
	{ 
		//If you change members here do not forget to increment object version (see bottom of this file)
		ar & boost::serialization::make_nvp("name",this->name); 
		ar & boost::serialization::make_nvp("parentTable",this->tablename);
		ar & boost::serialization::make_nvp("dimension",this->dimension);
		ar & boost::serialization::make_nvp("datatype",this->datatype);
		ar & boost::serialization::make_nvp("alternativeDType",this->alternativeTypeString);
		ar & boost::serialization::make_nvp("notNull",this->notNull);
	} 
};
typedef boost::shared_ptr<TableAttributeDesc> TableAttributeDescPtr;
//typedef boost::ptr_map<std::string, TableAttributeDesc> TableAttributeDescList;

typedef std::map<std::string, TableAttributeDescPtr, Utils::UpperCaseCompare> TableAttributeDescList;
typedef boost::shared_ptr<TableAttributeDescList> TableAttributeDescListPtr;

//-----------------------------------------------------------------------------------------------------------

class GST_API_EXPORT TableAttributeKeyDesc
	: public TableAttributeDesc
{
	friend class boost::serialization::access;

public:
	TableAttributeKeyDesc(const std::string& name, const std::string& tablename, DType type, int dimension, bool primaryKey, const std::string& alternativeType = "" );
	//TableAttributeKeyDesc(const Geometry::SimplexProperty & geomProperty, const FeatureClassDesc & target, bool primaryKey );
	TableAttributeKeyDesc();
	TableAttributeKeyDesc(const TableAttributeDesc & parent, bool primaryKey);

	bool isPrimaryKey() const;
	void setIsPrimaryKey( bool val );

	bool operator==( const TableAttributeKeyDesc & other ) const;

protected:
	bool primaryKey;

private:
	template <typename Archive> 
	void serialize(Archive &ar, const unsigned int version) 
	{ 
		//If you change members here do not forget to increment object version (see bottom of this file)
		ar & boost::serialization::make_nvp("TableAttributeDesc", boost::serialization::base_object<TableAttributeDesc>(*this) );
		ar & boost::serialization::make_nvp("primaryKey",this->primaryKey);
	} 
};
typedef boost::shared_ptr<TableAttributeKeyDesc> TableAttributeKeyDescPtr;
typedef std::vector<TableAttributeKeyDescPtr> TableAttributeKeyDescList;
typedef boost::shared_ptr<TableAttributeKeyDescList> TableAttributeKeyDescListPtr;

//-----------------------------------------------------------------------------------------------------------
}// namespace ClientUtils
}// namespace GST
BOOST_CLASS_EXPORT_KEY(GST::ClientUtils::TableAttributeDesc);
BOOST_CLASS_EXPORT_KEY(GST::ClientUtils::TableAttributeKeyDesc);

BOOST_CLASS_VERSION(GST::ClientUtils::TableAttributeDesc, 1)
BOOST_CLASS_VERSION(GST::ClientUtils::TableAttributeKeyDesc, 1)

#endif  //_TABLE_ATTRIBUTE_DESC_H_
